﻿// 30 Days Of .NET 6 - Day 17 - New Timer - PeriodicTimer，
// https://www.conradakunga.com/blog/30-days-of-net-6-day-17-new-timer-periodic-timer/
// 包括六种Timer介绍和30天学习.Net6的大量新特性，主页 https://www.conradakunga.com/blog/

namespace CSharpNewFeatures;

/// <summary>
/// 多线程相关测试。
/// </summary>
public class Demo_PeriodicTimer : CsharpDemoBase
{
    public bool testMode = true;
    public int value = 10;
    CancellationTokenSource source = new CancellationTokenSource();

    public override void Run()
    {
        Console.WriteLine("hello");
        if (testMode)
        {
            //var timer = new PeriodicTimer(TimeSpan.FromSeconds(10));
            //while (await timer.WaitForNextTickAsync())
            //{
            //    //Business logic
            //    print("hello");
            //    HeavyTask_NoReturn();
            //}
        }
        else
        {

        }
        try
        {

            // test1();
            // test2();
            test3();
        }
        catch (Exception ex)
        {
            print(ex.Message);
        }
        print("Value = " + value);
        for (int i = 0; i < 10; i++)
        {
            print("Looping...");
            Thread.Sleep(150);
        }
        source.Cancel();

        print("Value = " + value);
        for (int i = 0; i < 10; i++)
        {
            print("Looping...");
            Thread.Sleep(150);
        }
        print("Value = " + value);
        // Thread.Sleep(10*1000);
        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }

    private void HeavyTask_NoReturn()
    {
        print("Start");
        for (int i = 0; i <5; i++)
        {
            print($"Main Processing {i}...");
            Thread.Sleep(100);
        }
        print("Done.");
    }

    private async void test1()
    {
        var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
        cts.Token.Register(() => value = 20);
        // Create a timer that fires every 5 seconds
        using (var timer = new PeriodicTimer(TimeSpan.FromSeconds(0.2)))
        {
            // Wire it to fire an event after the specified period
            while (await timer.WaitForNextTickAsync(cts.Token))
            {
                print($"Firing Cancellable timer at {DateTime.Now}");
            }
        }
    }


    private async void test2()
    {
        try
        {
            // Create a cancellation token source
            var cts = new CancellationTokenSource();
            cts.Token.Register(() =>
            {
                value = 20;
                print("value is changed to 20.");
            });
            // Create a timer that fires every 200 milliseconds
            using (var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(200)))
            {
                // Create a counter to simulate logic
                var counter = 0;
                // Wire it to fire an event after the specified period
                while (await timer.WaitForNextTickAsync(cts.Token))
                {
                    // Cancel when the counter gets to 5
                    if (counter == 5)
                        cts.Cancel();
                    print($"Sub Processing Looping...");
                    counter++;
                }
            }
        }
        catch (Exception ex)
        {
            print(ex.Message);
            value = 30;
            print("value is changed to 30.");
        }
    }

    private async void test3()
    {
        try
        {
            // Create a cancellation token source
            source.Token.Register(() =>
            {
                value = 20;
                print("value is changed to 20.");
            });

            // Create a timer that fires every 200 milliseconds
            using (var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(200)))
            {
                // Create a counter to simulate logic
                var counter = 0;
                // Wire it to fire an event after the specified period
                while (await timer.WaitForNextTickAsync(source.Token))
                {
                    // Cancel when the counter gets to 5
                    print($"Sub Processing Looping...");
                    counter++;
                }
            }
        }
        catch (Exception ex)
        {
            print(ex.Message);
            value = 30;
            print("value is changed to 30.");
        }
    }
}

